namespace OasisCiq.Xml
{
    using System.Xml;
    using Xnal;

    public class XnalXmlWriter
    {
        private const string XmlNS = XmlNamespaces.NameAndAddress;
        private readonly CommonTypesXmlWriter ctWriter;
        private readonly XnlXmlWriter xnlWriter;
        private readonly XalXmlWriter xalWriter;
        private readonly XmlWriter writer;

        public XnalXmlWriter(XmlWriter writer)
        {
            this.writer = writer;
            ctWriter = new CommonTypesXmlWriter(writer);
            xnlWriter = new XnlXmlWriter(writer);
            xalWriter = new XalXmlWriter(writer);
        }

        public void WriteRecord(Record element)
        {
            if (element == null || element.PartyNames == null || element.Addresses == null ||
                element.PartyNames.Count < 1 || element.Addresses.Count < 1)
            {
                return;
            }

            writer.WriteStartElement("Record", XmlNS);
            if (element.RecordId != null)
            {
                writer.WriteAttributeString("RecordID", XmlNS, element.RecordId.ToString());
            }

            if (element.RecordIdType != null)
            {
                writer.WriteAttributeString("RecordIDType", XmlNS, element.RecordIdType.ToString());
            }

            ctWriter.WriteStatusList(element.Status, XmlNS);
            ctWriter.WriteValidityDateGroup(element);
            if (element.RecordKey != null)
            {
                writer.WriteAttributeString("RecordKey", XmlNS, element.RecordKey.ToString());
            }

            if (element.RecordKeyRef != null)
            {
                writer.WriteAttributeString("RecordKeyRef", XmlNS, element.RecordKeyRef.ToString());
            }

            ctWriter.WriteDataQualityGroup(element);
            ctWriter.WriteLanguageCodeGroup(element);
            ctWriter.WriteExtendedAttributes(element);
            foreach (var partyName in element.PartyNames)
            {
                xnlWriter.WritePartyName(partyName);
            }

            foreach (var address in element.Addresses)
            {
                xalWriter.WriteAddress(address);
            }

            writer.WriteEndElement();
        }

        public void WriteDesignation(Designation element)
        {
            if (element == null)
            {
                return;
            }

            writer.WriteStartElement("Designation", XmlNS);
            ctWriter.WriteExtendedAttributes(element);
            writer.WriteString(element.ToString());
            writer.WriteEndElement();
        }

        public void WriteDependencyName(DependencyName element)
        {
            if (element == null || element.Type == null)
            {
                return;
            }

            writer.WriteStartElement("DependencyName", XmlNS);
            xnlWriter.WritePartyNameAttributes(element);
            writer.WriteAttributeString("Type", XmlNS, element.Type.ToString());
            xnlWriter.WritePartyNameChildren(element);
            writer.WriteEndElement();
        }

        public void WriteAddressee(Addressee element)
        {
            if (element == null)
            {
                return;
            }

            writer.WriteStartElement("Addressee", XmlNS);
            ctWriter.WriteLanguageCodeGroup(element);
            ctWriter.WriteExtendedAttributes(element);
            if (element.Designations != null)
            {
                foreach (var designation in element.Designations)
                {
                    WriteDesignation(designation);
                }
            }

            xnlWriter.WritePartyName(element.PartyName);
            if (element.DependencyNames != null)
            {
                foreach (var dependencyName in element.DependencyNames)
                {
                    WriteDependencyName(dependencyName);
                }
            }

            writer.WriteEndElement();
        }

        public void WritePostalLabel(PostalLabel element)
        {
            if (element == null || element.Address == null)
            {
                return;
            }

            writer.WriteStartElement("PostalLabel", XmlNS);
            ctWriter.WriteStatusList(element.Status, XmlNS);
            ctWriter.WriteValidityDateGroup(element);
            ctWriter.WriteDataQualityGroup(element);
            ctWriter.WriteLanguageCodeGroup(element);
            ctWriter.WriteExtendedAttributes(element);
            if (element.Addressees != null)
            {
                foreach (var addresse in element.Addressees)
                {
                    WriteAddressee(addresse);
                }
            }

            xalWriter.WriteAddress(element.Address);
            writer.WriteEndElement();
        }
    }
}